#ifndef _UTILITIES_STRING_HELPER_
#define _UTILITIES_STRING_HELPER_

namespace science
{
	namespace utilities
	{
		class string_helper
		{
		public:
			static int is_sign(char c)
			{
				if (c == '+')
					return 1;
				else if (c == '-')
					return -1;
				else
					return 0;
			}

			static bool is_numeric_integer(char c)
			{
				return (c >= '0' && c <= '9');
			}

			static bool is_numeric_double(char c)
			{
				return (c >= '0' && c <= '9') || (c == '.');
			}

			static bool is_white_space(char c)
			{
				return (c == ' ' || c == '\0' || c == '\n' || c == '\r' || c == '\t');
			}

			static bool is_infinity(std::string str, unsigned int& index, double &value)
			{
				if (index >= str.size())
					return false;

				unsigned int start_index = index;
				value = 1;
				if (str[index] == '-')
				{
					value = -1;
					index++;
					if (index >= str.size())
						return false;
				}

				if (str[index] == 'I')
				{
					index++;
					if (index >= str.size())
						return false;
				}
				else
				{
					index = start_index; return false;
				}

				if (str[index] == 'n')
				{
					index++;
					if (index >= str.size())
						return false;
				}
				else
				{
					index = start_index; return false;
				}

				if (str[index] == 'f')
				{
					index++;
				}
				else
				{
					index = start_index; return false;
				}

				value = value * DBL_MAX;
				return true;
			}

			static std::string remove_white_chars(std::string str)
			{
				unsigned int index = 0;
				char c = str[index];
				std::string out = "";
				while (index < str.size())
				{
					if (!is_white_space(c))
						out.push_back(c);
					index++;
					c = str[index];
				}
				return out;
			}

			static int parse_int(std::string str, unsigned int& index)
			{
				if (index >= str.size())
					return 0;

				char c = str[index];

				int sign = is_sign(c);
				if (sign != 0)
					index++;
				else
					sign = 1;
				c = str[index];

				std::string num = "";
				while (is_numeric_integer(c) && index < str.size())
				{
					num.push_back(c);
					index++;
					c = str[index];
				}
				if (num.empty())
					index++;
				return atoi(num.c_str()) * sign;
			}

			static double parse_double(std::string str, unsigned int& index)
			{
				if (index >= str.size())
					return 0.0;

				double res;

				if (is_infinity(str, index, res))
					return res;
				else
				{
					if (index >= str.size())
						return 0.0;

					char c = str[index];

					int sign = is_sign(c);
					if (sign != 0)
						index++;
					else
						sign = 1;
					c = str[index];

					std::string num = "";
					while (is_numeric_double(c) && index < str.size())
					{
						num.push_back(c);
						index++;
						c = str[index];
					}
					if (num.empty())
						return 1;
					return atoi(num.c_str()) * sign;
				}
			}

		};
	}
}

#endif